package com.baturu.vin.changan.service.impl;

import com.baturu.experimental.constant.DiyStatus;
import com.baturu.experimental.dto.CarTypeDTO;
import com.baturu.experimental.dto.param.query.CarTypeQueryParam;
import com.baturu.experimental.service.CarTypeQueryService;
import com.baturu.vin.base.service.impl.VDSAnalyser;
import com.baturu.vin.changan.dal.dao.ChanganVinDAO;
import com.baturu.vin.changan.dto.ChanganVinDTO;
import com.baturu.vin.changan.dto.ChanganVinVdsDTO;
import com.baturu.vin.dto.EPCCarTypeDTO;
import com.baturu.vin.kit.VinModelYearUtil;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 长安VDS解析器
 *
 * @author :zhanjixun
 * @date : 2018/9/7 14:42
 */
@Slf4j
@Service("changanVDSAnalyser")
public class ChanganVDSAnalyser extends VDSAnalyser<ChanganVinDTO, EPCCarTypeDTO> {

    @Autowired
    private ChanganVinDAO vinDAO;
    @Autowired
    private CarTypeQueryService carTypeQueryService;

    @Override
    protected List<EPCCarTypeDTO> queryCarTypesByVds(ChanganVinDTO analyseResult) {
        List<ChanganVinVdsDTO> vinDTOs = analyseResult.getVinVdsDTOs();
        if (CollectionUtils.isEmpty(vinDTOs)) {
            return Collections.emptyList();
        }
        CarTypeQueryParam param = new CarTypeQueryParam();
        param.setStatus(Sets.newHashSet(1));
        param.setDiyStatuses(Sets.newHashSet(DiyStatus.THIRD));
        param.setNeedPagination(false);

        param.setBrandNames(vinDTOs.stream().map(ChanganVinVdsDTO::getBtrBrand).collect(Collectors.toSet()));
        param.setCarSystemNames(vinDTOs.stream().map(ChanganVinVdsDTO::getCarSystem).collect(Collectors.toSet()));

        param.setProductTimes(Sets.newHashSet(vinDTOs.get(0).getProductTime()));

        param.setTransmissionDescs(vinDTOs.stream().map(ChanganVinVdsDTO::getTransmissionDesc).collect(Collectors.toSet()));
        param.setEngineTypes(vinDTOs.stream().map(ChanganVinVdsDTO::getEngineType).collect(Collectors.toSet()));
        param.setCylinderVolume(vinDTOs.stream().map(ChanganVinVdsDTO::getCylinderVolume).collect(Collectors.toSet()));
        param.setFuelTypes(vinDTOs.stream().map(ChanganVinVdsDTO::getFuelType).collect(Collectors.toSet()));
        param.setDriveType(vinDTOs.stream().map(ChanganVinVdsDTO::getDriveType).collect(Collectors.toSet()));
        param.setCarType(vinDTOs.stream().map(ChanganVinVdsDTO::getCarType).collect(Collectors.toSet()));

        List<CarTypeDTO> data = carTypeQueryService.queryByParam(param).getData();
        if (CollectionUtils.isEmpty(data)) {
            return Collections.emptyList();
        }

        Set<String> btrIds = data.stream().filter(d -> vinDTOs.stream()
                .anyMatch(p ->
                        p.getCarSystem().equals(d.getCarSystemName()) &&
                                p.getBtrBrand().equals(d.getBrandName()) &&
                                p.getProductTime().equals(d.getProductTime()) &&
                                p.getTransmissionDesc().equals(d.getTransmissionDescription()) &&
                                p.getEngineType().equals(d.getEngineType()) &&
                                p.getCylinderVolume().equals(d.getCylinderVolume()) &&
                                p.getFuelType().equals(d.getFuelType()) &&
                                p.getDriveType().equals(d.getDriveType()) &&
                                p.getCarType().equals(d.getCarType())
                ))
                .map(CarTypeDTO::getBtrId).collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(btrIds)) {
            return Collections.emptyList();
        }

        return btrIds.stream().filter(StringUtils::isNotBlank).map(d -> {
            EPCCarTypeDTO epcCarTypeDTO = new EPCCarTypeDTO();
            epcCarTypeDTO.setBtrId(d);
            return epcCarTypeDTO;
        }).distinct().collect(Collectors.toList());
    }

    @Override
    protected ChanganVinDTO analyseVinCodeByVds(String vinCode) {
        String vinPre8 = vinCode.substring(0, 8);
        String vinPre11And12 = vinCode.substring(10, 12);
        List<ChanganVinVdsDTO> vinDTOs = vinDAO.queryVinByVinPre(vinPre8);
        if (CollectionUtils.isEmpty(vinDTOs)) {
            return null;
        }

        String vinYear = VinModelYearUtil.getVinYearByVinCode(vinCode);
        if (StringUtils.isBlank(vinYear)) {
            log.warn("vin第十位转换年份出现错误,需要检查,vinCode:{}", vinCode);
            return null;
        }
        vinDTOs.removeIf(p -> !("9999").equals(p.getProductTime()) && vinYear.compareTo(p.getProductTime()) > 0);
        if (CollectionUtils.isEmpty(vinDTOs)) {
            return null;
        }
        vinDTOs.forEach(p -> p.setProductTime(vinYear));

        List<ChanganVinVdsDTO> vinDTOsWith11And12 = vinDAO.queryVinByVinPre11And12(vinPre8, vinPre11And12);
        if (CollectionUtils.isEmpty(vinDTOsWith11And12)) {
            return ChanganVinDTO.builder().vinCode(vinCode).vinVdsDTOs(vinDTOs).build();
        }
        Set<String> carSystem = vinDTOsWith11And12.stream().map(ChanganVinVdsDTO::getCarSystem).collect(Collectors.toSet());
        Set<String> carType = vinDTOsWith11And12.stream().map(ChanganVinVdsDTO::getCarType).collect(Collectors.toSet());
        vinDTOs.removeIf(p -> carSystem.stream().noneMatch(d -> StringUtils.equals(p.getCarSystem(), d)));
        vinDTOs.removeIf(p -> carType.stream().noneMatch(d -> StringUtils.equals(p.getCarType(), d)));

        return ChanganVinDTO.builder().vinCode(vinCode).vinVdsDTOs(vinDTOs).build();
    }
}
